#include <stdio.h>
#include <string>
#include "tcp_data_handler.h"
#include "system_util.h"
#include "tcp_acceptor.h"
#include "application.h"


using namespace kingnet ;


class test_app ;
DECLARE_APPLICATION_INSTANCE(test_app) ;

class test_connection : public tcp_data_handler
{
public:
    test_connection()
    {
        m_last_time = time(0) ;
        m_timer.set_owner(this) ;
    }

    int get_packet_info(const char* data,int size,packet_info* pi)
    {
        if(memcmp(data+size-2,"\r\n",2)==0)
        {
            pi->data = data ;
            pi->size =size ;
            return 0 ;
        }
        else if ( size > 1500 )
        {
            return -1 ;
        }

        pi->data = data ;
        pi->size = size +1 ;
        return 0 ;
    }
    
    int process_packet(const packet_info* pi)
    {
        static char METHOD[] = "GET" ;
        if(memcmp(pi->data,METHOD,sizeof(METHOD)-1)!=0) error_return(-1,"invalid method") ;
        
        const char* query_string = pi->data + sizeof(METHOD)-1 ;
        int offset = strspn(query_string," ") ;
        if(offset < 1 ) error_return(-1,"no path") ;
        query_string += offset ;
        offset = strcspn(query_string," ") ;
        if(offset < 1 ) error_return(-1,"no version") ;
        std::string path(query_string,offset) ;
        printf("path:%s\n",path.c_str()) ;

        static char OK[] = "HTTP/1.1 200 OK\r\n" ;
        send(OK,sizeof(OK)-1,0) ;
        return -1 ;
    }
    
    void on_connected() ;
    void on_closed(int error_type,int error_no) ;


    void on_timeout(timer_manager* manager) ;

private:
    int m_last_time ;
    
    template_timer<test_connection,&test_connection::on_timeout> m_timer ; 


} ; 

class test_acceptor : public tcp_acceptor
{
public:
    int on_connection(int fd,sa_in_t* addr) ;

private:


};

class test_app : public application
{
public:
    int on_init()
    {
        m_acceptor.init(&reactor(),"0.0.0.0",80) ;
        conn_table = new test_connection[max_open_fd()] ;
        if(conn_table == 0 ) return -1 ;
        set_timer(10000) ;
        return 0 ;
    }

    void on_fini()
    {
        m_acceptor.fini() ;
        delete[] conn_table ;
    }

    void on_timer()
    {
        printf("app timer\n") ;
    }

public:
    test_connection* conn_table ;
private:
    test_acceptor m_acceptor ;

} ;

void test_connection::on_connected()
{
    m_last_time = time(0) ;
    get_app().add_timer(&m_timer,10000) ;
    printf("connection::on_connected\n") ;
}


void test_connection::on_closed(int error_type,int error_no)
{
    printf("disconnect type:%d\n",error_type) ;
    get_app().del_timer(&m_timer) ;
}

void test_connection::on_timeout(timer_manager* manager)
{
        printf("connection timer\n");
        fini() ;

}




int test_acceptor::on_connection(int fd,sa_in_t* addr)
{
    test_connection& conn = get_app().conn_table[fd] ;
    if( conn.init(m_reactor,fd)!=0) return -1 ;
    set_socket_nodelay(conn.get_id().fd) ;
    return 0 ;
}


IMPLEMENT_APPLICATION_INSTANCE(test_app) ;
IMPLEMENT_MAIN() ;
